package cn.cheegon.blog.service.impl;

import cn.cheegon.blog.common.api.CommonPage;
import cn.cheegon.blog.common.exception.Asserts;
import cn.cheegon.blog.entity.dto.BlogAEditDto;
import cn.cheegon.blog.entity.dto.CmsBlogDto;
import cn.cheegon.blog.entity.dto.PmsTagDto;
import cn.cheegon.blog.entity.req.BlogTagReq;
import cn.cheegon.blog.entity.rsp.BlogListRsp;
import cn.cheegon.blog.mapper.*;
import cn.cheegon.blog.model.*;
import cn.cheegon.blog.service.CmsBlogService;
import cn.cheegon.blog.service.PmsTagService;
import cn.cheegon.blog.service.UmsAdminService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 博客表 服务实现类
 * </p>
 *
 * @author cheegon
 * @since 2024-06-21
 */
@Service
public class CmsBlogServiceImpl extends ServiceImpl<CmsBlogMapper, CmsBlog> implements CmsBlogService {
    @Autowired
    PmsTagMapper tagMapper;

    @Autowired
    PmsTypeMapper typeMapper;

    @Autowired
    CmsBlogTagsMapper blogTagsMapper;

    @Autowired
    UmsAdminMapper adminMapper;

    @Autowired
    UmsAdminService adminService;

    @Autowired
    PmsTagService tagService;

    @Override
    public CmsBlogDto getItem(Long id) {
        //  return BeanUtil.toBean(this.baseMapper.selectById(id), CmsBlogDto.class);
        return getBlogMoreInfo(this.baseMapper.selectById(id));
    }

    @Override
    public CommonPage<BlogListRsp> getList(String kwd, Long tagId, Long typeId, int pageNum, int pageSize) {

        QueryWrapper<CmsBlog> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("create_time");
        if (typeId != null) {
            wrapper.eq("type_id", typeId);
        }
        if (StrUtil.isNotEmpty(kwd)) {
            //   wrapper.and(i->i.like("title",kwd).or().like("description",kwd));
            wrapper.and(i -> i.like("title", kwd));
        }
        if (tagId != null) {
            QueryWrapper<CmsBlogTags> wrapper2 = new QueryWrapper<>();
            wrapper2.eq("tag_id", tagId);
            List<CmsBlogTags> cmsBlogTags = blogTagsMapper.selectList(wrapper2);
            if (!CollectionUtils.isEmpty(cmsBlogTags)) {
                List<Long> tagIds = cmsBlogTags.stream().map(CmsBlogTags::getBlogId).collect(Collectors.toList());
                wrapper.in("id", tagIds);
            }
        }
        Page<CmsBlog> page = this.baseMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
        List<CmsBlog> records = page.getRecords();
        if (records.isEmpty()) {
            return CommonPage.emptyPage(page);
        }
        return CommonPage.restPage(page, getBlogListMoreInfo(records));
    }

    /**
     * 获取blog关联信息
     *
     * @param cmsBlog
     * @return
     */
    private CmsBlogDto getBlogMoreInfo(CmsBlog cmsBlog) {
        if (cmsBlog == null) {
            Asserts.fail("该博客不存在");
        }
        //获取用户相关信息
        UmsAdmin umsAdmin = adminMapper.selectById(cmsBlog.getId());
        //获取type信息
        PmsType pmsType = typeMapper.selectById(cmsBlog.getTypeId());
        //获取tag相关信息
        QueryWrapper<CmsBlogTags> wrapper2 = new QueryWrapper<>();
        wrapper2.eq("blog_id", cmsBlog.getId());
        List<CmsBlogTags> cmsBlogTags = blogTagsMapper.selectList(wrapper2);

        List<Long> tagIdList = cmsBlogTags.stream().map(CmsBlogTags::getTagId).distinct().toList();
        List<PmsTag> pmsTags = new ArrayList<>();
        if (!CollectionUtils.isEmpty(tagIdList)) {
            pmsTags = tagMapper.selectBatchIds(tagIdList);
        }

        Map<Long, PmsTag> pmsTagMap = pmsTags.stream().collect(Collectors.toMap(PmsTag::getId, it -> it));

        Map<Long, List<CmsBlogTags>> blogTagGroupMap = cmsBlogTags.stream().collect(Collectors.groupingBy(CmsBlogTags::getBlogId, Collectors.toList()));
        //数据填充
        CmsBlogDto target = new CmsBlogDto();
        BeanUtils.copyProperties(cmsBlog, target);
        //user
        if (umsAdmin != null) {
            target.setAvatar(umsAdmin.getAvatar());
            target.setNickname(umsAdmin.getNickname());
            target.setUid(umsAdmin.getId());
        }
        //type
        if (pmsType != null) {
            target.setTypeName(pmsType.getName());
        }
        //tag
        List<CmsBlogTags> blogTagsList = blogTagGroupMap.get(cmsBlog.getId());
        if (blogTagsList != null) {
            List<PmsTag> oriTagList = blogTagsList.stream().map(item -> pmsTagMap.get(item.getTagId())).toList();
            List<PmsTagDto> pmsTagDtos = BeanUtil.copyToList(oriTagList, PmsTagDto.class);
            target.setTagList(pmsTagDtos);
        }
        return target;
    }

    /**
     * 获取blog关联信息
     *
     * @param records
     * @return
     */
    private List<BlogListRsp> getBlogListMoreInfo(List<CmsBlog> records) {
        //获取用户相关信息
        List<Long> uidList = records.stream().map(CmsBlog::getUserId).distinct().toList();
        List<UmsAdmin> umsAdmins = adminMapper.selectBatchIds(uidList);
        Map<Long, UmsAdmin> adminMap = umsAdmins.stream().collect(Collectors.toMap(UmsAdmin::getId, it -> it));
        //获取type信息
        List<Long> typeIdList = records.stream().map(CmsBlog::getTypeId).distinct().toList();
        List<PmsType> pmsTypes = typeMapper.selectBatchIds(typeIdList);
        Map<Long, PmsType> pmsTypeMap = pmsTypes.stream().collect(Collectors.toMap(PmsType::getId, it -> it));
        //获取tag相关信息
        List<Long> blogIdList = records.stream().map(CmsBlog::getId).toList();
        QueryWrapper<CmsBlogTags> wrapper2 = new QueryWrapper<>();
        wrapper2.in("blog_id", blogIdList);
        List<CmsBlogTags> cmsBlogTags = blogTagsMapper.selectList(wrapper2);

        List<Long> tagIdList = cmsBlogTags.stream().map(CmsBlogTags::getTagId).distinct().toList();
        List<PmsTag> pmsTags = new ArrayList<>();
        if (!CollectionUtils.isEmpty(tagIdList)) {
            pmsTags = tagMapper.selectBatchIds(tagIdList);
        }
        Map<Long, PmsTag> pmsTagMap = pmsTags.stream().collect(Collectors.toMap(PmsTag::getId, it -> it));

        Map<Long, List<CmsBlogTags>> blogTagGroupMap = cmsBlogTags.stream().collect(Collectors.groupingBy(CmsBlogTags::getBlogId, Collectors.toList()));
        //数据填充
        return records.stream().map(it -> {
            BlogListRsp target = new BlogListRsp();
            BeanUtils.copyProperties(it, target);
            //用户
            UmsAdmin umsAdmin = adminMap.get(it.getUserId());
            target.setAvatar(umsAdmin.getAvatar());
            target.setNickname(umsAdmin.getNickname());
            //type
            PmsType pmsType = pmsTypeMap.get(it.getTypeId());
            if (pmsType != null) {
                target.setTypeName(pmsType.getName());
            }
            //tag
            List<CmsBlogTags> blogTagsList = blogTagGroupMap.get(it.getId());
            if (blogTagsList != null) {
                List<PmsTag> oriTagList = blogTagsList.stream().map(item -> pmsTagMap.get(item.getTagId())).toList();
                List<PmsTagDto> pmsTagDtos = BeanUtil.copyToList(oriTagList, PmsTagDto.class);
                target.setTagList(pmsTagDtos);
            }
            return target;
        }).toList();
    }

    @Override
    public List<BlogListRsp> getRecommendList(int size) {
        QueryWrapper<CmsBlog> wrapper = new QueryWrapper<>();
        wrapper.eq("recommend", true);
        wrapper.orderByDesc("create_time");
        wrapper.last("limit " + size);
        List<CmsBlog> cmsBlogs = this.baseMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(cmsBlogs)) {
            return List.of();
        }
        return BeanUtil.copyToList(cmsBlogs, BlogListRsp.class);
    }

    @Override
    public void getReportView(Long id) {
        CmsBlog cmsBlog = this.baseMapper.selectById(id);
        if (cmsBlog != null) {
            Integer i = cmsBlog.getViews() + 1;
            cmsBlog.setViews(i);
        }

        baseMapper.updateById(cmsBlog);
    }

    @Override
    public void add(BlogAEditDto dto) {
        CmsBlog bean = BeanUtil.toBean(dto, CmsBlog.class);
        UmsAdmin currUser = adminService.getCurrUser();
        bean.setUserId(currUser.getId());
        baseMapper.insert(bean);
        // 添加tagList
        if (!CollectionUtils.isEmpty(dto.getTagIds())) {
            dto.getTagIds().forEach(it -> {
                blogTagsMapper.insert(new CmsBlogTags(bean.getId(), it));
            });
        }
    }

    @Override
    public void edit(BlogAEditDto dto) {
        CmsBlog bean = BeanUtil.toBean(dto, CmsBlog.class);
        baseMapper.updateById(bean);
        // 查找tags
        QueryWrapper<CmsBlogTags> wrapper = new QueryWrapper<>();
        wrapper.eq("blog_id", bean.getId());
        List<CmsBlogTags> cmsBlogTags = blogTagsMapper.selectList(wrapper);
        List<Long> tagIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(cmsBlogTags)) {
            tagIds.addAll(cmsBlogTags.stream().map(CmsBlogTags::getTagId).toList());
        }
        List<Long> tagList = CollectionUtils.isEmpty(dto.getTagIds()) ? new ArrayList<>() : dto.getTagIds();
        // 删除
        if (!CollectionUtils.isEmpty(tagIds)) {
            tagIds.forEach(it -> {
                if (!tagList.contains(it)) {
                    blogTagsMapper.delete(new QueryWrapper<CmsBlogTags>()
                            .eq("blog_id", bean.getId())
                            .eq("tag_id", it)
                    );
                }
            });
        }
        // 添加不存在
        if (!CollectionUtils.isEmpty(tagList)) {
            tagList.forEach(it -> {
                if (!tagIds.contains(it)) {
                    blogTagsMapper.insert(new CmsBlogTags(bean.getId(), it));
                }
            });
        }
    }

    @Override
    public void del(Long id) {
        baseMapper.deleteById(id);
    }

    @Override
    public void addTag(BlogTagReq dto) {
        if (dto.getType() == 1) {
            PmsTag tag = new PmsTag();
            tag.setName(dto.getName());
            PmsTag add = tagService.add(tag);
            dto.setTagId(add.getId());
        }
        List<CmsBlogTags> cmsBlogTags = blogTagsMapper.selectList(new QueryWrapper<CmsBlogTags>()
                .eq("blog_id", dto.getId())
                .eq("tag_id", dto.getTagId())
        );
        if (CollectionUtils.isEmpty(cmsBlogTags)) {
            blogTagsMapper.insert(new CmsBlogTags(dto.getId(), dto.getTagId()));
        }
    }

    @Override
    public void delTag(BlogTagReq dto) {
        blogTagsMapper.delete(new QueryWrapper<CmsBlogTags>()
                .eq("blog_id", dto.getId())
                .eq("tag_id", dto.getTagId())
        );
    }
}
